#!/usr/bin/env python
# encoding: utf-8


"""
@file: sanjiaoxing_zonghe.py
@time: 2017/3/22 下午2:09
"""
from mathsolver.functions.base import *
from mathsolver.functions.budengshi import common_opers as co
from mathsolver.functions.sanjiao import sanjiaoxing_utils as san_utils
from mathsolver.functions.sanjiao.sanjiao_constants import SanJiaoXingLineSubs
from mathsolver.functions.sanjiao import sanjiaoxing_utils as sjx_utils
from mathsolver.functions.sanjiao.sanjiao_objects import SanJiaoXing


# 三角函数的综合性问题

# 求三角行某条边上的高
# Input1 paramer1:BaseEqs(关于三角形边角关系的等式); paramer2:baseLine(指定的边)
# Input2 paramer1:baseLine(制定的边) 搜寻关于三角形边角关系的等式
# 060 在 △ABC中,AB=3 ,BC=\\sqrt {13},AC=4,则边 AC上的高为( )
class BianShangGao001(BaseFunction):
    def solver(self, *args):
        known = {}
        if len(args) == 2 and isinstance(args[0], BaseEqs):  # Input1
            eqs = args[0].sympify()
            known.update(dict(eqs))
        elif len(args) == 1:  # input2
            known.update(self.known)
        else:
            raise Exception('Type Match Error')
        target_line = args[0].sympify()
        target_line = sjx_utils.preprocess_base_triangle_expr(target_line)
        tmp_eqs = san_utils.known_triangle_eqs(self.known)
        eqs_list = tmp_eqs.sympify()
        new_eqs = []
        line_subs = (('baseLine(AB)', 'c'), ('baseLine(AC)', 'b'), ('baseLine(BC)', 'a'))
        for tmp_eq in eqs_list:
            e_l, e_r = tmp_eq
            e_l = e_l.subs(line_subs).subs(SanJiaoXingLineSubs)
            e_r = e_r.subs(line_subs).subs(SanJiaoXingLineSubs)
            new_eqs.append([e_l, e_r])
        new_eqs = BaseEqs(new_eqs)
        eq_sets = SanJiaoXing.simu_trian_eqs(new_eqs)  # 联立方程组
        abc_values_list = []
        self.steps.append(['由题意可利用边角转换 ', ''])
        for base_eqs in eq_sets:
            self.steps.append(['联立方程组', base_eqs.printing()])
            try:
                abc_values = co.isolve_eqs(base_eqs, ['a', 'b', 'c'])
                if abc_values:  # 有可能解出来是空集
                    for tmp_set in abc_values:
                        self.steps.append(['求得', BaseEqs(tmp_set).printing()])
                    abc_values_list.extend(abc_values)
            except Exception:
                pass
        # 合法的边
        abc_values_list = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values_list)
        # 是否满足两边之和大于第三边
        abc_values_list = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values_list)
        # 锐角三角形，钝角三角形 等等条件
        if self.search('triangle_type'):
            triangle_type = str(list(self.search('triangle_type'))[0])
            if triangle_type == 'acute_triangle':
                abc_values_list = filter(lambda _: san_utils.acute_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
            elif triangle_type == 'obtuse_triangle':
                abc_values_list = filter(lambda _: san_utils.obtuse_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
        a_vs, b_vs, c_vs = [], [], []
        self.steps.append(['验证求得:', ''])
        for abc_values in abc_values_list:
            a_v, b_v, c_v = abc_values
            self.steps.append([BaseEqs(abc_values).printing(), ''])
            a_vs.append(a_v[1])
            b_vs.append(b_v[1])
            c_vs.append(c_v[1])
        a_b_c_values = zip(a_vs, b_vs, c_vs)
        if len(a_b_c_values) == 1:
            a_value, b_value, c_value = a_b_c_values[0]
            triangle_obj = SanJiaoXing(a=a_value, b=b_value, c=c_value)
            line_height = triangle_obj.height(target_line)
            self.steps.append(['所以边 ' + new_latex(target_line), '上的高为' + new_latex(line_height)])
            self.output.append(BaseNumber(line_height))
        return self


class BianShangGao(BaseFunction):
    CLS = [BianShangGao001, ]

    def solver(self, *args):
        solve_r = None
        for cl in BianShangGao.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r.known = self.known
                solve_r = solve_r.solver(*args)
                break
            except Exception:
                solve_r = None
        if not solve_r:
            raise Exception('try fail')
        return solve_r


# 求出三条边后 利用中线定理
class BianShangZhongXian001(BaseFunction):
    def solver(self, *args):
        known = {}
        if len(args) == 2 and isinstance(args[0], BaseEqs):  # Input1
            eqs = args[0].sympify()
            known.update(dict(eqs))
        elif len(args) == 1:  # input2
            known.update(self.known)
        else:
            raise Exception('Type Match Error')
        target_line = args[0].sympify()
        target_line = sjx_utils.preprocess_base_triangle_expr(target_line)
        tmp_eqs = san_utils.known_triangle_eqs(self.known)
        eqs_list = tmp_eqs.sympify()
        new_eqs = []
        line_subs = (('baseLine(AB)', 'c'), ('baseLine(AC)', 'b'), ('baseLine(BC)', 'a'))
        for tmp_eq in eqs_list:
            e_l, e_r = tmp_eq
            e_l = e_l.subs(line_subs).subs(SanJiaoXingLineSubs).subs(sjx_utils.get_triangle_line_subs())
            e_r = e_r.subs(line_subs).subs(SanJiaoXingLineSubs).subs(sjx_utils.get_triangle_line_subs())
            new_eqs.append([e_l, e_r])
        new_eqs = BaseEqs(new_eqs)
        eq_sets = SanJiaoXing.simu_trian_eqs(new_eqs)  # 联立方程组
        abc_values_list = []
        self.steps.append(['由题意可利用边角转换 ', ''])
        for base_eqs in eq_sets:
            self.steps.append(['联立方程组', base_eqs.printing()])
            abc_values = co.solve_poly_eqs(base_eqs)
            for tmp_set in abc_values:
                self.steps.append(['求得', BaseEqs(tmp_set).printing()])
            abc_values_list.extend(abc_values)
        # 合法的边
        abc_values_list = filter(
            lambda _: san_utils.legal_sided(_[0][1]) and san_utils.legal_sided(_[1][1]) and san_utils.legal_sided(
                _[2][1]), abc_values_list)
        # 是否满足两边之和大于第三边
        abc_values_list = filter(lambda _: san_utils.legal_sides((_[0][1], _[1][1], _[2][1])), abc_values_list)
        # 锐角三角形，钝角三角形 等等条件
        if self.search('triangle_type'):
            triangle_type = str(list(self.search('triangle_type'))[0])
            if triangle_type == 'acute_triangle':
                abc_values_list = filter(lambda _: san_utils.acute_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
            elif triangle_type == 'obtuse_triangle':
                abc_values_list = filter(lambda _: san_utils.obtuse_triangled((_[0][1], _[1][1], _[2][1])),
                                         abc_values_list)
        a_vs, b_vs, c_vs = [], [], []
        self.steps.append(['验证求得:', ''])
        for abc_values in abc_values_list:
            a_v, b_v, c_v = abc_values
            self.steps.append([BaseEqs(abc_values).printing(), ''])
            a_vs.append(a_v[1])
            b_vs.append(b_v[1])
            c_vs.append(c_v[1])
        a_b_c_values = zip(a_vs, b_vs, c_vs)  # a, b, c三条边
        if len(a_b_c_values) == 1:
            a_value, b_value, c_value = a_b_c_values[0]
            center_line = SanJiaoXing(a=a_value, b=b_value, c=c_value).center_line(target_line)
            self.steps.append(['所以边 ' + new_latex(target_line), '上的高为' + new_latex(center_line)])
            self.output.append(BaseNumber(center_line))
        return self


class BianShangZhongXian(BaseFunction):
    CLS = [BianShangZhongXian001, ]

    def solver(self, *args):
        solve_r = None
        for cl in BianShangZhongXian.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r.known = self.known
                solve_r = solve_r.solver(*args)
                break
            except Exception:
                solve_r = None
        if not solve_r:
            raise 'try fail'
        return solve_r
